home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’95 / Menu Controls / BetterFeedback.cp < prev    next >
Encoding:
Text File  |  1995-06-24  |  8.8 KB  |  292 lines  |  [TEXT/MPS ]

  1. // Copyright © 1994-95 by Apple Computer, Inc. All rights reserved.
  2. // BetterFeedbackCmd.cp
  3.  
  4. #ifndef __BETTERFEEDBACK__
  5. #include "BetterFeedback.h"
  6. #endif
  7.  
  8. #ifndef __UMACAPPUTILITIES__
  9. #include <UMacAppUtilities.h>
  10. #endif
  11.  
  12. #ifndef __UVIEW__
  13. #include <UView.h>
  14. #endif
  15.  
  16. #ifndef __UWINDOW__
  17. #include <UWindow.h>
  18. #endif
  19.  
  20. #ifndef __UFAILURE__
  21. #include <UFailure.h>
  22. #endif
  23.  
  24. #ifndef __LOWMEM__
  25. #include <LowMem.h>
  26. #endif
  27.  
  28. #ifndef __TOOLUTILS__
  29. #include <ToolUtils.h>
  30. #endif
  31.  
  32. #ifndef __RETRACE__
  33. #include <Retrace.h>
  34. #endif
  35.  
  36. #ifndef __QUICKDRAW__
  37. #include <Quickdraw.h>
  38. #endif
  39.  
  40. #ifndef __DEVICES__
  41. #include <Devices.h>
  42. #endif
  43.  
  44. #ifndef __START__
  45. #include <Start.h>
  46. #endif
  47.  
  48. #ifndef __TRAPS__
  49. #include <Traps.h>
  50. #endif
  51.  
  52. //----------------------------------------------------------------------------------------
  53.  
  54. struct QElemWithA5AndCounter
  55. {
  56.     QElemWithA5AndCounter();            // Constructor
  57.     long OldA5;                            // A place to store the old value of A5, since 
  58.                                         // when debugging the compiler trashes the value 
  59.                                         // of A0 for any locals in the VBL task thus making 
  60.                                         // the pointer to the ParamBlockRec unavailable
  61.     long A5;                            // The value of A5 will be stored here to be
  62.                                         // available at VBL time
  63.     VBLTask q;                            // our VBL queue element
  64. };
  65.  
  66. inline QElemWithA5AndCounter::QElemWithA5AndCounter()
  67. {
  68.     OldA5 = 0;
  69.     A5 = 0;
  70. }
  71.  
  72. typedef QElemWithA5AndCounter* QElemWithA5AndCounterPtr;
  73.  
  74. //----------------------------------------------------------------------------------------
  75. // Globals
  76.  
  77. long gCounter;                        // our counter incremented in the VBL task
  78. short gSlot;                        // the slot our VBL is installed in
  79. QElemWithA5AndCounter gOurVBLTask;    // our VBL task record
  80.  
  81. //----------------------------------------------------------------------------------------
  82. // IncOurVBLCounter - our VBL task that increments the counter which is tested in 
  83. //                      WaitBetterFeedback
  84. //                    NOTE: must be resident! We don't want a segment load at interrupt time
  85. //----------------------------------------------------------------------------------------
  86. #pragma push
  87. #pragma trace off
  88.  
  89. #pragma segment ARes
  90.  
  91. pascal void IncOurVBLCounter(
  92. #if qPowerPC
  93.                              VBLTaskPtr vblTaskPtr
  94. #endif
  95.                                                 )
  96. {
  97.     const short theOffset = sizeof(long) * 2;
  98.         
  99. #if qPowerPC
  100.     // if we are running native PowerPC, the runtime architecture passes us a pointer to our
  101.     // VBLTask as a parameter
  102.     QElemWithA5AndCounterPtr qElemPtr = (QElemWithA5AndCounterPtr)((long)vblTaskPtr - theOffset);
  103. #else
  104.     // if we are 680X0, we have to grab the VBLTask pointer from A0, using GetParmBlockPtr
  105.     QElemWithA5AndCounterPtr qElemPtr = (QElemWithA5AndCounterPtr)(GetParmBlockPtr() - theOffset);
  106. #endif
  107.     
  108.     gOurVBLTask.OldA5 = SetA5(qElemPtr->A5);
  109.     gOurVBLTask.q.vblCount = 1;        // reprime the pump
  110.     gCounter++;                                    // increment our counter
  111.     SetA5(gOurVBLTask.OldA5);
  112. }
  113. #pragma pop
  114.  
  115. //----------------------------------------------------------------------------------------
  116. // GetAVideoSlot - Return the video slot associated with the view's port
  117. //----------------------------------------------------------------------------------------
  118. #pragma segment ADoCommand
  119.  
  120. short GetAVideoSlot(TView* aView)
  121. {
  122.     TWindow* aWindow;
  123.     DefVideoRec aDefVideoRec;
  124.     GDHandle aGDHandle;
  125.     CRect aRect;
  126.     AuxDCEHandle anAuxDCEHandle;
  127.  
  128.     aWindow = aView->GetWindow();
  129.     if (aWindow == NULL) {
  130.         GetVideoDefault(&aDefVideoRec);
  131.         return aDefVideoRec.sdSlot;
  132.     }
  133.     else {
  134.         aGDHandle = aWindow->GetMaxIntersectedDevice(aRect);
  135.         anAuxDCEHandle = (AuxDCEHandle)GetDCtlEntry((*aGDHandle)->gdRefNum);
  136.         return (*anAuxDCEHandle)->dCtlSlot;
  137.     }
  138. }
  139.  
  140. //----------------------------------------------------------------------------------------
  141. // InstallOurVBL - Install a VBL task to increment a counter
  142. //                   Used by TShapeCommand's TrackFeedback method
  143. //----------------------------------------------------------------------------------------
  144. #pragma segment ADoCommand
  145.  
  146. void InstallOurVBL(TView* aView)
  147. {
  148.     gCounter = 0;
  149.     gOurVBLTask.q.qType = vType;
  150.     gOurVBLTask.q.vblAddr = NewVBLProc(StripLong(IncOurVBLCounter));
  151.     FailNIL(gOurVBLTask.q.vblAddr);
  152.     gOurVBLTask.q.vblCount = 1;
  153.     gOurVBLTask.q.vblPhase = 0;
  154.     gOurVBLTask.A5 = SetCurrentA5();    // make the A5 world available to the VBL task
  155.  
  156.     // Install the VBL task 
  157.     if (TrapExists(_SlotVInstall)) {
  158.         gSlot = GetAVideoSlot(aView);
  159.         FailOSErr(SlotVInstall((QElemPtr) & gOurVBLTask.q, gSlot));
  160.     }
  161.     else
  162.         FailOSErr(VInstall((QElemPtr) & gOurVBLTask.q));
  163. }
  164.  
  165. //----------------------------------------------------------------------------------------
  166. // RemoveOurVBL - Remove the VBL task we installed
  167. //----------------------------------------------------------------------------------------
  168. #pragma segment ADoCommand
  169.  
  170. void RemoveOurVBL()
  171. {
  172.     if (TrapExists(_SlotVRemove))
  173.         FailOSErr(SlotVRemove((QElemPtr) & gOurVBLTask.q, gSlot));
  174.     else
  175.         FailOSErr(VRemove((QElemPtr) & gOurVBLTask.q));
  176. }
  177.  
  178. //========================================================================================
  179. // CLASS TBetterFeedbackCmd
  180. //========================================================================================
  181. #undef Inherited
  182. #define Inherited TTracker
  183.  
  184. #pragma segment AInit
  185. MA_DEFINE_CLASS_M1(TBetterFeedbackCmd, Inherited);
  186.  
  187. //----------------------------------------------------------------------------------------
  188. // TBetterFeedbackCmd Constructor
  189. //----------------------------------------------------------------------------------------
  190. #pragma segment AInit
  191.  
  192. TBetterFeedbackCmd::TBetterFeedbackCmd()
  193. {
  194.     fBetterFeedbackInstalled = !kInstall;
  195.     fBetterFeedbackDesired = false;
  196. }
  197.  
  198. //----------------------------------------------------------------------------------------
  199. // TBetterFeedbackCmd::IBetterFeedbackCmd: 
  200. //----------------------------------------------------------------------------------------
  201. #pragma segment AInit
  202.  
  203. void TBetterFeedbackCmd::IBetterFeedbackCmd(CommandNumber itsCommandNumber,
  204.                                             TCommandHandler* itsContext,
  205.                                             Boolean canUndo,
  206.                                             Boolean causesChange,
  207.                                             TObject* objectToNotify,
  208.                                             TView* itsView,
  209.                                             TScroller* itsScroller,
  210.                                             VPoint itsMouse,
  211.                                             Boolean betterFeedbackDesired)
  212. {
  213.     this->ITracker(itsCommandNumber, itsContext, canUndo, causesChange, objectToNotify, itsView, itsScroller, itsMouse);
  214.     fBetterFeedbackDesired = betterFeedbackDesired;
  215. }
  216.  
  217. //----------------------------------------------------------------------------------------
  218. // TBetterFeedbackCmd::Free: 
  219. //----------------------------------------------------------------------------------------
  220. #pragma segment ADoCommand
  221.  
  222. void TBetterFeedbackCmd::Free()    // Override
  223. {
  224.     this->BetterFeedback(!kInstall);
  225.     Inherited::Free();
  226. }
  227.  
  228. //----------------------------------------------------------------------------------------
  229. // TBetterFeedbackCmd::TrackMouse: 
  230. //----------------------------------------------------------------------------------------
  231. #pragma segment ADoCommand
  232.  
  233. TTracker* TBetterFeedbackCmd::TrackMouse(TrackPhase aTrackPhase,
  234.                                          VPoint& /*anchorPoint*/,
  235.                                          VPoint& /*previousPoint*/,
  236.                                          VPoint& /*nextPoint*/,
  237.                                          Boolean /*mouseDidMove*/)    // Override
  238. {
  239.     if (aTrackPhase == trackRelease)
  240.         this->BetterFeedback(!kInstall);
  241.     return this;
  242. }
  243.  
  244. //----------------------------------------------------------------------------------------
  245. // TBetterFeedbackCmd::TrackFeedback: 
  246. //----------------------------------------------------------------------------------------
  247. #pragma segment ADoCommand
  248.  
  249. void TBetterFeedbackCmd::TrackFeedback(TrackPhase /*aTrackPhase*/,
  250.                                        const VPoint& /*anchorPoint*/,
  251.                                        const VPoint& /*previousPoint*/,
  252.                                        const VPoint& /*nextPoint*/,
  253.                                        Boolean mouseDidMove,
  254.                                        Boolean turnItOn)    // Override
  255. {
  256.     if (mouseDidMove || !turnItOn)
  257.         this->WaitBetterFeedback();
  258. }
  259.  
  260. //----------------------------------------------------------------------------------------
  261. // TBetterFeedbackCmd::BetterFeedback: 
  262. //----------------------------------------------------------------------------------------
  263. #pragma segment ADoCommand
  264.  
  265. void TBetterFeedbackCmd::BetterFeedback(Boolean install)
  266. {
  267.     if (fBetterFeedbackDesired == kBetterFeedbackDesired)
  268.     {
  269.         if ((install == kInstall) && (fBetterFeedbackInstalled == !kInstall))
  270.             InstallOurVBL(fView);
  271.         else if ((install == !kInstall) && (fBetterFeedbackInstalled == kInstall))
  272.             RemoveOurVBL();
  273.         fBetterFeedbackInstalled = install;
  274.     }
  275. }
  276.  
  277. //----------------------------------------------------------------------------------------
  278. // TBetterFeedbackCmd::WaitBetterFeedback: 
  279. //----------------------------------------------------------------------------------------
  280. #pragma segment ADoCommand
  281.  
  282. void TBetterFeedbackCmd::WaitBetterFeedback()
  283. {
  284.     if (fBetterFeedbackDesired == kBetterFeedbackDesired)
  285.     {
  286.         if (fBetterFeedbackInstalled == !kInstall)
  287.             this->BetterFeedback(kInstall);
  288.         long t = gCounter;            // we'll wait til screen refresh
  289.         while (t == gCounter) ;        // let's hope this changes soon
  290.     }
  291. }
  292.